package com.pxst.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pxst.exception.BusinessException;
import com.pxst.resp.ApiResp;
import com.pxst.sys.entity.SysConfig;
import com.pxst.sys.entity.SysConfigDetail;
import com.pxst.sys.mapper.SysConfigDetailMapper;
import com.pxst.sys.mapper.SysConfigMapper;
import com.pxst.sys.req.*;
import com.pxst.sys.service.SysConfigService;
import com.pxst.utils.RedisUtils;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import icu.mhb.mybatisplus.plugln.core.JoinLambdaWrapper;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.security.Key;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.pxst.enums.RedisKeyEnums.CONFIG_LIST;
import static com.pxst.enums.RedisKeyEnums.CONFIG_KEY;

/**
* @author Administrator
* @description 针对表【sys_config(系统配置主表)】的数据库操作Service实现
* @createDate 2023-09-05 16:31:36
*/
@Service
public class SysConfigServiceImpl extends JoinServiceImpl<SysConfigMapper, SysConfig> implements SysConfigService {

    @Resource
    private SysConfigMapper sysConfigMapper;
    @Resource
    private SysConfigDetailMapper sysConfigDetailMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    @Transactional
    public ApiResp addConfig(ConfigInsertRsp configRsp) {
        //添加主表
        //在配置主表中添加一条记录
        SysConfig sysConfig = new SysConfig();
        //判断name或code是否已经存在
        QueryWrapper<SysConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", configRsp.getCode());
        SysConfig sysConfig1 = sysConfigMapper.selectOne(queryWrapper);
        if (ObjectUtils.isNotEmpty(sysConfig1)) {
            return ApiResp.bussError("配置编码已经存在");
        }
        queryWrapper.clear();
        queryWrapper.eq("name", configRsp.getName());
        SysConfig sysConfig2 = sysConfigMapper.selectOne(queryWrapper);
        if (ObjectUtils.isNotEmpty(sysConfig2)) {
            return ApiResp.bussError("配置名称已经存在");
        }

        sysConfig.setCode(configRsp.getCode());
        sysConfig.setName(configRsp.getName());
        sysConfigMapper.insert(sysConfig);

        //保存到redis中的数据
        ConfigRedisRsp configRedisRsp = new ConfigRedisRsp();
        BeanUtils.copyProperties(sysConfig, configRedisRsp);

        //将数据添加到Redis中
        //生成key
        String key = CONFIG_KEY.getKey() + sysConfig.getCode();
        //将数据存入Redis中
        redisUtils.set(key, configRedisRsp);

        //将数据添加到Redis主配置列表中
        //生成key
        String key1 = CONFIG_LIST.getKey();
        //保存到Redis中的数据
        ConfigRedisRspAll configRedisRspAll = new ConfigRedisRspAll();
        BeanUtils.copyProperties(sysConfig, configRedisRspAll);
        //查到Redis中的主配置列表
        Map<String, ConfigRedisRspAll> stringConfigRedisRspAllMap = (Map<String, ConfigRedisRspAll>) redisUtils.get(key1);
        if (ObjectUtils.isEmpty(stringConfigRedisRspAllMap)) {
            HashMap<String, ConfigRedisRspAll> stringConfigRedisRspAllMap1 = new HashMap<>();
            stringConfigRedisRspAllMap1.put(configRedisRspAll.getCode(),configRedisRspAll);
            //将数据存入Redis中
            redisUtils.set(key1, stringConfigRedisRspAllMap1);
        }else {
            stringConfigRedisRspAllMap.put(configRedisRspAll.getCode(),configRedisRspAll);
            //将数据存入Redis中
            redisUtils.set(key1, stringConfigRedisRspAllMap);
        }

        return ApiResp.sucess();
    }

    @Override
    @Transactional
    public ApiResp addConfigSub(ConfigInsertRspSub configRsp) {
        //验证配置主表是否存在
        SysConfig sysConfig = sysConfigMapper.selectById(configRsp.getId());
        if (ObjectUtils.isEmpty(sysConfig)) {
            return ApiResp.bussError("配置主表不存在");
        }

        //在配置子表中添加记录
        SysConfigDetail sysConfigDetail = new SysConfigDetail();

        //判断配置子表的code是否已经存在
        QueryWrapper<SysConfigDetail> eq1 = new QueryWrapper<SysConfigDetail>().eq("code", configRsp.getCode());
        SysConfigDetail sysConfigDetail1 = sysConfigDetailMapper.selectOne(eq1);
        if (ObjectUtils.isNotEmpty(sysConfigDetail1)) {
            return ApiResp.bussError("配置子表编码已经存在");
        }

        sysConfigDetail.setCode(configRsp.getCode());
        sysConfigDetail.setValue(configRsp.getValue());
        sysConfigDetail.setRemark(configRsp.getRemark());
        sysConfigDetail.setConfigId(configRsp.getId());
        sysConfigDetailMapper.insert(sysConfigDetail);

        //保存到redis中的数据
        ConfigRedisRspSub configRedisRspSub = new ConfigRedisRspSub();
        BeanUtils.copyProperties(sysConfigDetail, configRedisRspSub);

        //将数据更新到Redis中
        //生成key
        String key = CONFIG_KEY.getKey() + sysConfig.getCode();
        //查到Redis中的数据
        ConfigRedisRsp configRedisRsp = (ConfigRedisRsp) redisUtils.get(key);
        //将新的数据添加到Redis中
        if (ObjectUtils.isEmpty(configRedisRsp.getConfigRedisRspSubMap())) {
            HashMap<String, ConfigRedisRspSub> stringConfigRedisRspSubHashMap = new HashMap<>();
            stringConfigRedisRspSubHashMap.put(sysConfigDetail.getCode(), configRedisRspSub);
            configRedisRsp.setConfigRedisRspSubMap(stringConfigRedisRspSubHashMap);
        }
        configRedisRsp.getConfigRedisRspSubMap().put(sysConfigDetail.getCode(), configRedisRspSub);
        //将数据存入Redis中
        redisUtils.set(key, configRedisRsp);

        return ApiResp.sucess();
    }

    @Override
    @Transactional
    public ApiResp deleteConfig(ConfigDeleteRsp configDeleteRsp) {
        //status为0时，删除配置主表和配置子表中的数据,为1时，删除配置子表中的数据
        if (configDeleteRsp.getStatus() == 0) {
            //拿到删除数据的code
            QueryWrapper<SysConfig> eq1 = new QueryWrapper<SysConfig>().eq("id", configDeleteRsp.getId());
            SysConfig sysConfig = sysConfigMapper.selectOne(eq1);
            if (ObjectUtils.isEmpty(sysConfig)) {
                return ApiResp.bussError("id不存在");
            }
            //删除配置主表中的数据
            sysConfigMapper.deleteById(configDeleteRsp.getId());
            //删除配置子表中的数据
            QueryWrapper<SysConfigDetail> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("config_id", configDeleteRsp.getId());
            sysConfigDetailMapper.delete(queryWrapper);

            //删除Redis中的数据
            //生成key
            String key = CONFIG_KEY.getKey() + sysConfig.getCode();
            //删除Redis中的数据
            redisUtils.del(key);

            //删除Redis主配置列表中的数据
            //生成key
            String key1 = CONFIG_LIST.getKey();
            //查到Redis中的主配置列表
            Map<String, ConfigRedisRspAll> stringConfigRedisRspAllMap = (Map<String, ConfigRedisRspAll>) redisUtils.get(key1);
            //删除Redis中的数据
            stringConfigRedisRspAllMap.remove(sysConfig.getCode());
            //将数据存入Redis中
            redisUtils.set(key1, stringConfigRedisRspAllMap);
        } else if (configDeleteRsp.getStatus() == 1) {
            //拿到删除数据的code
            QueryWrapper<SysConfigDetail> eq = new QueryWrapper<SysConfigDetail>().eq("id", configDeleteRsp.getId());
            SysConfigDetail sysConfigDetail = sysConfigDetailMapper.selectOne(eq);
            if (ObjectUtils.isEmpty(sysConfigDetail)) {
                return ApiResp.bussError("id不存在");
            }
            //拿到配置主表的code，用于删除Redis中的数据
            QueryWrapper<SysConfig> eq1 = new QueryWrapper<SysConfig>().eq("id", sysConfigDetail.getConfigId());
            SysConfig sysConfig = sysConfigMapper.selectOne(eq1);
            //删除配置子表中的数据
            sysConfigDetailMapper.deleteById(configDeleteRsp.getId());

            //删除Redis中的数据
            //生成key
            String key = CONFIG_KEY.getKey() + sysConfig.getCode();
            //查到Redis中的数据
            ConfigRedisRsp configRedisRsp = (ConfigRedisRsp) redisUtils.get(key);
            //删除子配置列表中的数据
            configRedisRsp.getConfigRedisRspSubMap().remove(sysConfigDetail.getCode());
            //将数据存入Redis中
            redisUtils.set(key, configRedisRsp);
        }

        return ApiResp.sucess();
    }

    @Override
    public ApiResp getConfigAll() {
        //生成key
        String key = CONFIG_LIST.getKey();
        //查到Redis中的数据
        Map<String, ConfigRedisRspAll> stringConfigRedisRspAllMap = (Map<String, ConfigRedisRspAll>) redisUtils.get(key);

        return ApiResp.sucess(stringConfigRedisRspAllMap);
    }

    @Override
    public ApiResp getConfigByCode(String code) {
        //生成key
        String key = CONFIG_KEY.getKey() + code;
        //查到Redis中的数据
        ConfigRedisRsp configRedisRsp = (ConfigRedisRsp) redisUtils.get(key);

        return ApiResp.sucess(configRedisRsp);
    }

    @Override
    @Transactional
    public ApiResp updateConfig(SysConfig sysConfig) {
        //根据id查询数据是否存在
        SysConfig sysConfig1 = sysConfigMapper.selectById(sysConfig.getId());
        if (ObjectUtils.isEmpty(sysConfig1)){
            return ApiResp.bussError("id错误");
        }
        //修改配置主表中的数据
        //判断code是否重复
        QueryWrapper<SysConfig> eq = new QueryWrapper<SysConfig>().eq("code", sysConfig.getCode());
        SysConfig sysConfig2 = sysConfigMapper.selectOne(eq);
        if (ObjectUtils.isNotEmpty(sysConfig2)){
            return ApiResp.bussError("code重复");
        }
        //判断name是否重复
        QueryWrapper<SysConfig> eq1 = new QueryWrapper<SysConfig>().eq("name", sysConfig.getName());
        SysConfig sysConfig3 = sysConfigMapper.selectOne(eq1);
        if (ObjectUtils.isNotEmpty(sysConfig3)){
            return ApiResp.bussError("名字重复");
        }
        sysConfigMapper.updateById(sysConfig);

        //修改Redis中的数据
        //生成key
        String key = CONFIG_KEY.getKey() + sysConfig1.getCode();
        //查到Redis中的数据
        ConfigRedisRsp configRedisRsp = (ConfigRedisRsp) redisUtils.get(key);
        //修改Redis中的数据
        if (!ObjectUtils.isEmpty(sysConfig.getName())){
            configRedisRsp.setName(sysConfig.getName());
        }
        //判断是否修改了code，如果修改了code，需要修改Redis中的key
        if (!ObjectUtils.isEmpty(sysConfig.getCode())){
            configRedisRsp.setCode(sysConfig.getCode());
            //生成新的key
            key = CONFIG_KEY.getKey() + sysConfig.getCode();
            //删除旧的key
            redisUtils.del(CONFIG_KEY.getKey() + sysConfig1.getCode());
        }
        //将数据存入Redis中
        redisUtils.set(key, configRedisRsp);

        //修改Redis主配置列表中的数据
        //生成key
        String key1 = CONFIG_LIST.getKey();
        //查到Redis中的主配置列表
        Map<String, ConfigRedisRspAll> stringConfigRedisRspAllMap = (Map<String, ConfigRedisRspAll>) redisUtils.get(key1);
        //修改Redis中的数据
        ConfigRedisRspAll configRedisRspAll = stringConfigRedisRspAllMap.get(sysConfig1.getCode());
        if (!ObjectUtils.isEmpty(sysConfig.getName())){
            configRedisRspAll.setName(sysConfig.getName());
        }
        //判断code是否修改，如果修改了，要修改主配置列表中的key
        if (!ObjectUtils.isEmpty(sysConfig.getCode())){
            configRedisRspAll.setCode(sysConfig.getCode());

            ConfigRedisRspAll configRedisRspAll1 = new ConfigRedisRspAll();
            BeanUtils.copyProperties(configRedisRspAll, configRedisRspAll1);
            stringConfigRedisRspAllMap.remove(sysConfig1.getCode());
            stringConfigRedisRspAllMap.put(sysConfig.getCode(), configRedisRspAll1);
        }
        //将数据存入Redis中
        redisUtils.set(key1, stringConfigRedisRspAllMap);

        return ApiResp.sucess();
    }

    @Override
    public ApiResp updateConfigSub(SysConfigDetail sysConfigDetail) {
        //根据id查询数据是否存在
        SysConfigDetail sysConfigDetail1 = (SysConfigDetail) sysConfigDetailMapper.selectById(sysConfigDetail.getId());
        if (ObjectUtils.isEmpty(sysConfigDetail1)){
            return ApiResp.bussError("id错误");
        }
        //修改配置子表中的数据
        //判断code是否重复
        QueryWrapper<SysConfigDetail> eq = new QueryWrapper<SysConfigDetail>().eq("code", sysConfigDetail.getCode());
        SysConfigDetail sysConfigDetail2 = sysConfigDetailMapper.selectOne(eq);
        if (ObjectUtils.isNotEmpty(sysConfigDetail2)){
            return ApiResp.bussError("编码重复");
        }
        //判断value是否重复
        QueryWrapper<SysConfigDetail> eq1 = new QueryWrapper<SysConfigDetail>().eq("value", sysConfigDetail.getValue())
                                                                               .eq("config_id", sysConfigDetail1.getConfigId());
        SysConfigDetail sysConfigDetail3 = sysConfigDetailMapper.selectOne(eq1);
        if (ObjectUtils.isNotEmpty(sysConfigDetail3)){
            return ApiResp.bussError("该主配置中值重复");
        }
        sysConfigDetailMapper.updateById(sysConfigDetail);
        //拿到配置主表的code，用于修改Redis中的数据
        QueryWrapper<SysConfig> eq2 = new QueryWrapper<SysConfig>().eq("id", sysConfigDetail1.getConfigId());
        SysConfig sysConfig = sysConfigMapper.selectOne(eq2);

        //修改Redis中的数据
        //生成key
        String key = CONFIG_KEY.getKey() + sysConfig.getCode();
        //查到Redis中的数据
        ConfigRedisRsp configRedisRsp = (ConfigRedisRsp) redisUtils.get(key);
        //修改Redis中的数据
        if (!ObjectUtils.isEmpty(sysConfigDetail.getValue())){
            configRedisRsp.getConfigRedisRspSubMap().get(sysConfigDetail1.getCode()).setValue(sysConfigDetail.getValue());
        }
        if (!ObjectUtils.isEmpty(sysConfigDetail.getRemark())){
            configRedisRsp.getConfigRedisRspSubMap().get(sysConfigDetail1.getCode()).setRemark(sysConfigDetail.getRemark());
        }
        //判断code是否修改，如果修改了，要修改子配置列表中的key，将原来的key删除，再添加新的key
        if (!ObjectUtils.isEmpty(sysConfigDetail.getCode())) {
            configRedisRsp.getConfigRedisRspSubMap().get(sysConfigDetail1.getCode()).setCode(sysConfigDetail.getCode());

            ConfigRedisRspSub configRedisRspSub = new ConfigRedisRspSub();
            BeanUtils.copyProperties(configRedisRsp.getConfigRedisRspSubMap().get(sysConfigDetail1.getCode()), configRedisRspSub);
            configRedisRsp.getConfigRedisRspSubMap().remove(sysConfigDetail1.getCode());
            configRedisRsp.getConfigRedisRspSubMap().put(sysConfigDetail.getCode(), configRedisRspSub);
        }

        //将数据存入Redis中
        redisUtils.set(key, configRedisRsp);

        return ApiResp.sucess();
    }

    @Override
    public String getSubCode(String code, String subKey) {
        ConfigRedisRsp configRedisRsp = (ConfigRedisRsp) redisUtils.get(CONFIG_KEY.getKey() + code);
        if (ObjectUtils.isEmpty(configRedisRsp)) {
            // 查询配置主表信息
            SysConfig config = getOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getCode, code));
            if (ObjectUtils.isEmpty(config)) {
                throw new BusinessException("配置主表信息不存在");
            }
            // 查询配置子表信息
            List<SysConfigDetail> configDetails = sysConfigDetailMapper.selectList(new LambdaQueryWrapper<SysConfigDetail>()
                    .eq(SysConfigDetail::getConfigId, config.getId()));
            if (ObjectUtils.isEmpty(configDetails) || configDetails.size() == 0) {
                throw new BusinessException("配置子表信息不存在");
            }
            // 封装数据
            BeanUtils.copyProperties(config, configRedisRsp);
            Map<String, ConfigRedisRspSub> map = new HashMap<>();
            configDetails.forEach(configDetail -> {
                ConfigRedisRspSub configRedisRspSub = new ConfigRedisRspSub();
                BeanUtils.copyProperties(configDetail, configRedisRspSub);
                map.put(configDetail.getCode(), configRedisRspSub);
            });
            configRedisRsp.setConfigRedisRspSubMap(map);
            // 存入redis
            redisUtils.set(CONFIG_KEY.getKey() + code, configRedisRsp);
        }
        Map<String, ConfigRedisRspSub> configRedisRspSubMap = configRedisRsp.getConfigRedisRspSubMap();
        ConfigRedisRspSub configRedisRspSub = configRedisRspSubMap.get(subKey);
        return ObjectUtils.isNotEmpty(configRedisRspSub) ? configRedisRspSub.getValue() : null;
    }

}




